#include <string.h>
#include "BasicLinkedList.h"
#include "Allocator.h"
#include "Exception.h"
#include "Log.h"


namespace illib {
	namespace BasicLinkedList{
		Iterator::Iterator(List& list, bool end) :
			current_(list.head_)
		{
			if(end) current_ = list.tail_;
		}
		Node* Iterator::current() {
			return current_;
		}
		void Iterator::current(Node* current) {
			current_ = current;
		}
		Node* Iterator::next() {
			if(current_ == 0) return 0;
			current_ = current_->next_;
			return current_;
		}
		Node* Iterator::prev() {
			if(current_ == 0) return 0;
			current_ = current_->prev_;
			return current_;
		}
		Node::Node() :
			next_(0),
			prev_(0)
		{

		}
		List::List() :
			head_(0), tail_(0), length_(0) {

		}
		size_t List::length() {
			return length_;
		}
		void List::clear() {
			tail_ = 0;
			head_ = 0;
			length_ = 0;
		}
		Node* List::head() {
			return head_;
		}
		Node* List::tail() {
			return tail_;
		}
		Node* List::add(Node& element, size_t index) {
			if (index > length_)
				return 0;
			element.next_ = 0;
			element.prev_ = 0;
			if (index == 0) {
				if (length_ == 0) {
					head_ = tail_ = &element;
				} else {
					element.next_ = head_;
					head_->prev_ = &element;
					head_ = &element;
				}
			} else if (index == length_) {
				element.prev_ = tail_;
				tail_->next_ = &element;
				tail_ = &element;
			} else {
				Node *ptr = get(index - 1);
				element.prev_ = ptr;
				element.next_ = ptr->next_;
				ptr->next_->prev_ = &element;
				ptr->next_ = &element;
			}
			length_++;
			return &element;
		}
		Node* List::remove(size_t index) {
			Node* element = get(index);
			if(element == 0) return 0;
			return remove(*element);
		}
		Node* List::remove(Node & element) {
			if(element.next_){
				element.next_->prev_ = element.prev_;
			}
			if(element.prev_){
				element.prev_->next_ = element.next_;
			}
			if(&element == head_) head_ = element.next_;
			if(&element == tail_) tail_ = element.prev_;
			length_--;
			element.next_ = 0;
			element.prev_ = 0;
			return &element;
		}
		Node* List::remove(Iterator &iterator){
			Node *element = iterator.current();
			if(element == 0) return 0;
			iterator.next();
			Node* removed = remove(*element);
			return removed;
		}
		Node* List::get(size_t index) {
			if (index >= length_)
				return 0;
			size_t forwards = index;
			size_t backwards = length_ - index - 1;
			Node *ptr = 0;
			if (forwards <= backwards) {
				ptr = head_;
				for (size_t i = 0; i < forwards; i++) {
					ptr = ptr->next_;
				}
			} else {
				ptr = tail_;
				for (size_t i = 0; i < backwards; i++) {
					ptr = ptr->prev_;
				}
			}
			return ptr;
		}
	};
}
